//
//  HXUserAccount.swift
//  DemoSinaWeibo
//
//  Created by Mon on 15/11/29.
//  Copyright © 2015年 Mon. All rights reserved.
//

import UIKit

// 用户账户对象,保存用户数据
// 将对象归档到沙盒保存,需要实现NSCoding协议
class HXUserAccount: NSObject, NSCoding {
    
    //直接在判断的时候调用账户是否有账号,不合理,应该在用户账号类中提供方法,直接让外界调用
    // MARK: - 属性
    /// 类属性
    class var userLogin: Bool {
        get {
            // 默认是true,有账号
            return HXUserAccount.loadUserAccount() != nil
        }
    }
    
    /// 用于调用access_token，接口获取授权后的access token
    var access_token: String?
    
    /// access_token的生命周期，单位是秒数 --- 新浪文档解析该类型为String,实际上是数字,故该属性需要改变类型,否则报错 --- 而且该值不能为可选,基本数据类型都需要设置初始值
    var expires_in: NSTimeInterval = 0 {
        //在属性监视器下直接为过期的时间属性赋值
        didSet {
            //设置过期时间
            expirseDate = NSDate(timeIntervalSinceNow: expires_in)
        }
    }
    
    /// 拿到的时间格式不是我们想要的,定义属性保存时间对其进行转换
    var expirseDate: NSDate?
    
    /// 当前授权用户的UID
    var uid: String?
    
    /// 用户头像地址（大图），180×180像素
    var avatar_large: String?
    
    /// 用户昵称
    var screen_name: String?
    
    /// 字典转模型
    init(dict: [String : AnyObject]) {
    //调用父类的init()方法时,上面的key需要设置？可选类型;因为数据没有加载,key没有值,没有值的话,下面无法使用KVC
        super.init()
        setValuesForKeysWithDictionary(dict)
    }
    
    /// 加载用户信息
    func loadUserInfo() {
        //测试获取网络用户数据
        HXNetWorkTool.sharedNetWorkTool.loadUserInfo { (result, error) -> () in
            if result == nil || error != nil{
                print("用户数据加载失败")
                return
            }
            print("用户数据加载成功：\(result)")
            
            // 设置属性
            self.screen_name = result!["screen_name"] as? String
            self.avatar_large = result!["avatar_large"] as? String
            
            // 对象获取了两个属性,更新userAccount账户属性
            HXUserAccount.userAccount = self
            
            // 保存起来
            self.saveAccount()
        }
    }
    
    /// 保存到document下的/account.plist文件中,由于多处使用沙盒路径,故写个静态属性,对象方法和类方法都可以访问
    static let plistPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! + "/account.plist"
    
    /// 保存账户信息到沙盒
    func saveAccount() {
        //归档当前类
        NSKeyedArchiver.archiveRootObject(self, toFile: HXUserAccount.plistPath)
    }
    /*
        项目中经常需要使用到CZUserAccount,如果每次调用loadUserAccount,都会去沙盒解档一个账户.这样是比较消耗性能.
        当没有账户,去沙盒解档一个.如果解档账户成功,将它保存在内存中,以后直接访问内存中的账户.可以提高性能
    */
    
    /// 定义：记住内存中的账户 ---> 提高程序效率
    private static var userAccount: HXUserAccount?
    
    /// 读取保存在沙盒里面的账户信息 --- 类方法方便调用,无需进行创建对象 --> 有数据就需要返回对象
    class func loadUserAccount() -> HXUserAccount? {
        
        //1.判断内存中是否有账户
        if userAccount == nil {
            //如果没有账户,加载在沙盒中加载(从沙盒加载,可能成功,可能失败)
            userAccount = NSKeyedUnarchiver.unarchiveObjectWithFile(plistPath) as? HXUserAccount
            print("在沙盒中加载:\(userAccount)")
        }else {
            print("从内存中加载")
        }
        
        //2.判断内存中是否有账户,有的话在判断时间是否过期
        if userAccount != nil && userAccount?.expirseDate?.compare(NSDate()) == NSComparisonResult.OrderedDescending {
            //有账户并且时间没有过期
//            print("有账户并且时间没有过期")
            return userAccount
        }
        
//        //解档 --- 判断能否成功解档对象,
//        // 判断accessToken是否过期,过期就不可有 --> 可选绑定
//        if let account = NSKeyedUnarchiver.unarchiveObjectWithFile(plistPath) as? HXUserAccount {
//            //来到这里说明解档成功
//                //判断accessToken是否过期 进行时间比较 --> OrderedDescending 升序
////            // 测试时间过期案例
////            account.expirseDate = NSDate(timeIntervalSinceNow: -100)
//            
//            if account.expirseDate?.compare(NSDate()) == NSComparisonResult.OrderedDescending {
//                //时间没有过期
//                print("没有过期")
//                return account
//            }
//        }
        
        return nil
    }
    
    
    // MARK: - 实现NSCoding代理方法
    /// 解档 --- 注意解档类型自动转换,需要强转为原来的类型 ---> 必须赋值给属性
    required init?(coder aDecoder: NSCoder) {
        access_token = aDecoder.decodeObjectForKey("access_token") as? String
        expires_in = aDecoder.decodeDoubleForKey("expires_in")
        expirseDate = aDecoder.decodeObjectForKey("expirseData") as? NSDate
        uid = aDecoder.decodeObjectForKey("uid") as? String
        screen_name = aDecoder.decodeObjectForKey("screen_name") as? String
        avatar_large = aDecoder.decodeObjectForKey("avatar_large") as? String
    }
    
    /// 归档 --- 找不到归档类型的都为object类型,基本数据类型的是什么属性就是什么属性
    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(access_token, forKey: "access_token")
        aCoder.encodeDouble(expires_in, forKey: "expires_in")
        aCoder.encodeObject(expirseDate, forKey: "expirseData")
        aCoder.encodeObject(uid, forKey: "uid")
        aCoder.encodeObject(screen_name, forKey: "screen_name")
        aCoder.encodeObject(avatar_large, forKey: "avatar_large")
    }
    
    /// 当使用KVC字典转模型的时候,无法找到一些我们不需要的key(remind_in)时调用,忽略掉那些key --- 下面方法只需要空实现即可
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
    
    /// 调试模型信息,看看数据是否有
    override var description: String {
        return "access_token:\(access_token) expires_in:\(expires_in) uid:\(uid) expirseData:\(expirseDate) screen_name:\(screen_name)"
    }

}
